package com.jack.payment.controller.webhook;


import com.alibaba.fastjson.JSONObject;
import com.jack.payment.cache.AppointDetailServiceImpl;
import com.jack.payment.constant.enums.AliTradeStatusEnum;
import com.jack.payment.constant.enums.PaymentStatusEnum;
import com.jack.payment.constant.enums.StripeTradeEnum;
import com.jack.payment.entity.common.BusinessException;
import com.jack.payment.entity.generate.payment.PaymentAttachModel;
import com.jack.payment.entity.third.AliCallBackModel;
import com.jack.payment.rabbitmq.RabbitQueueSendUtil;
import com.jack.payment.service.common.PaymentSuccessService;
import com.jack.payment.util.common.BigDecimalUtil;
import com.jack.payment.util.common.TimeUtil;
import com.jack.payment.util.redis.GenerateId;
import com.stripe.model.Event;
import com.stripe.model.PaymentIntent;
import com.stripe.model.StripeObject;
import com.stripe.net.ApiResource;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;

@Controller
@RequestMapping(value = "/callBack")
public class PaymentNotifyController {
    private Logger log = LoggerFactory.getLogger(PaymentNotifyController.class);

    private final static String SUCCESS_CHAR = "success";

    @Autowired
    private GenerateId generateId;
    @Autowired
    private PaymentSuccessService paymentSuccessService;
    @Autowired
    private RabbitQueueSendUtil rabbitQueueSendUtil;
    @Autowired
    private AppointDetailServiceImpl appointDetailService;

    @Operation(summary = "支付宝支付成功后回调地址")
    @RequestMapping(value = "/alipayNotify", method = {RequestMethod.POST})
    @ResponseBody
    public String alipayNotifySuccess(AliCallBackModel aliCallBackModel) throws BusinessException {
        Long currentTime = TimeUtil.getCurrentTime();
        if (aliCallBackModel.getTrade_status().equals(AliTradeStatusEnum.SUCCESS.getStatus())
                && aliCallBackModel.getRefund_fee() == null) {
            log.info("支付宝成功支付回调");
            String mqId = String.valueOf(generateId.generateMQId());
            String orderNo = aliCallBackModel.getBody();
            PaymentAttachModel getPaymentAttachDetail = appointDetailService.getAppointPaymentAttachDetail(orderNo);
            PaymentAttachModel paymentAttachModel = new PaymentAttachModel().builder()
                    .status(PaymentStatusEnum.PAY.getStat())
                    .channel("1")
                    .orderNo(orderNo)
                    .channelNo(aliCallBackModel.getTrade_no())
                    .actualAmount(aliCallBackModel.getReceipt_amount())
                    .paymentMqId(mqId)
                    .successTime(currentTime)
                    .payerContent(JSONObject.toJSONString(aliCallBackModel))
                    .build();
            paymentSuccessService.paymentSuccessBoHandler(paymentAttachModel, getPaymentAttachDetail);
            //rabbitQueueSendUtil.paymentSuccessQueueMessage(orderNo, currentTime, mqId);
        }
        return SUCCESS_CHAR;
    }

    @Operation(summary = "stripe 支付成功后的回调地址")
    @RequestMapping(value = "/stripeNotify", method = {RequestMethod.POST})
    @ResponseBody
    public String stripeNotifySuccess(@RequestBody String notify) throws BusinessException {
        Long currentTime = TimeUtil.getCurrentTime();
        Event event = ApiResource.GSON.fromJson(notify, Event.class);
        if (event.getType().equals(StripeTradeEnum.SUCCESSDED.getStatus())) {
            log.info("stripe成功支付回调");
            StripeObject stripeObject = event.getData().getObject();
            PaymentIntent paymentIntent = (PaymentIntent) stripeObject;
            String mqId = String.valueOf(generateId.generateMQId());
            BigDecimal actualAmount = BigDecimalUtil.divideBigDeimalHoured(paymentIntent.getAmount());
            String orderNo = paymentIntent.getMetadata().get("attach");
            PaymentAttachModel getPaymentAttachDetail = appointDetailService.getAppointPaymentAttachDetail(orderNo);
            PaymentAttachModel paymentAttachModel = new PaymentAttachModel().builder()
                    .status(PaymentStatusEnum.PAY.getStat())
                    .channel("2")
                    .orderNo(orderNo)
                    .channelNo(paymentIntent.getId())
                    .actualAmount(actualAmount)
                    .paymentMqId(mqId)
                    .successTime(currentTime)
                    .payerContent(notify)
                    .build();
            paymentSuccessService.paymentSuccessBoHandler(paymentAttachModel, getPaymentAttachDetail);
            // rabbitQueueSendUtil.paymentSuccessQueueMessage(orderNo, currentTime, mqId);
        }
        return SUCCESS_CHAR;
    }

    @Operation(summary = "wechat 支付成功后的回调地址")
    @RequestMapping(value = "wechatNotify", method = {RequestMethod.POST})
    @ResponseBody
    public String wechatNotifySuccess(@RequestBody String notify) {
        log.info("Wechat 支付成功, 回调数据");
        Long currentTime = TimeUtil.getCurrentTime();
        return null;
    }



    @Operation(summary = "支付成功后回调地址,  并将处理支付业务")
    @GetMapping("/api/v1/stream")
    public void streamData(HttpServletResponse response) throws IOException {
        // 设置响应头以表明这是一个流，并且我们不知道内容长度
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Connection", "keep-alive");
        // 获取PrintWriter用于写入响应体
        PrintWriter writer = response.getWriter();

        // 模拟一个数据流，例如逐行发送数据
        for (int i = 0; i < 100; i++) {
            // 发送SSE（Server-Sent Events）格式的数据，或者简单的文本行
            writer.println("data: Line " + i + " at " + System.currentTimeMillis());
            writer.println(); // SSE事件之间需要一个空行
            writer.flush(); // 刷新输出流，确保数据被立即发送

            // 模拟数据发送的间隔
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 关闭流（在实际应用中，你可能希望保持流打开以持续发送数据）
        writer.close();
    }
}
